﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using M3G;

/**
 * 注意:Sampleのテストはもっと必要
 * まだKeyframeのほうを実装していないのでいまはこれだけ
 * */


namespace MyTestProject {
    public class TestAnimationTrack {
        [Fact]
        public void TestConstructor1 () {
            var sequence = new KeyframeSequence (16, 1, KeyframeSequence.Step);
            var property = AnimationTrack.Alpha;
            var track = new AnimationTrack (sequence, property);

            Assert.Equal (sequence, track.KeyframeSequence);
            Assert.Equal (property, track.TargetProperty);
            Assert.Equal (null, track.Controller);
        }

        [Fact]
        public void TestConstrctor2 () {
            var sequence = new KeyframeSequence (16, 1, KeyframeSequence.Step);
            var basicType = ShaderVariableType.Int;
            var track = new AnimationTrack (sequence, basicType, true);

            Assert.Equal (sequence, track.KeyframeSequence);
            Assert.Equal ((int)basicType, track.TargetProperty);
            Assert.Equal (null, track.Controller);
            Assert.Equal (true, track.NormalizeEnabled);
        }

        [Fact]
        public void TestSetKeyframe () {
            var sequence1 = new KeyframeSequence (16, 1, KeyframeSequence.Step);
            var sequence2 = new KeyframeSequence (16, 1, KeyframeSequence.Step);
            var property  = AnimationTrack.Alpha;
            var track = new AnimationTrack (sequence1, property);

            track.SetKeyframeSequence (sequence2);

            Assert.Equal (sequence2, track.KeyframeSequence);
        }

        [Fact]
        public void TestSetController () {
            var sequence = new KeyframeSequence (16, 1, KeyframeSequence.Step);
            var basicType = ShaderVariableType.Int;
            var track = new AnimationTrack (sequence, basicType, true);
            var controller = new AnimationController ();

            track.SetController (controller);

            Assert.Equal (controller, track.Controller);
        }

        /**
         * もっともシンプルなSampleのテスト
         * Keyframe : component=1, channel=1, interp=Step
         * Controller : speed=1, ref points=0,0, weight=1
         * */
        [Fact (Skip = "KeyframeSequenceが未実装")]
        public void TestSample1 () {
            var controller = new AnimationController ();
            var sequence = new KeyframeSequence (4, 1, KeyframeSequence.Step);
            for (var i=0; i < 4; i++) {
                sequence.SetKeyframe (i, i, new float[] { i });
            }
            var track = new AnimationTrack (sequence, AnimationTrack.Alpha);
            track.SetController (controller);

            Assert.Equal (0.0f, track.Sample (0, 0));  // index=0, ch=0
            Assert.Equal (1.0f, track.Sample (1, 0));  // index=1, ch=0
            Assert.Equal (2.0f, track.Sample (2, 0));  // index=2, ch=0
            Assert.Equal (3.0f, track.Sample (3, 0));  // index=3, ch=0
        }

        /**
         * マルチチャンネルのSampleのテスト
         * Keyframe : component=1, channel=4, interp=Step
         *  idx:  0   1   2   3
         *  -------------------
         *  ch0:  0   1   2   3
         *  ch1:  4   5   6   7
         *  ch2:  8   9  10  11
         *  ch3: 12  13  14  15
         *  -------------------
         * Controller : speed=1, ref points=0,0, weight=1
         * */
        [Fact (Skip = "KeyframeSequenceが未実装")]
        public void TestSample2 () {
            var controller = new AnimationController ();
            var sequence = new KeyframeSequence (4, 4, 1, KeyframeSequence.Step);
            for (var i=0; i < 4; i++) {
                sequence.SetKeyframeTime (i, i);
                for (var ch=0; ch < 4; ch++) {
                    sequence.SetKeyframeValue (ch, i, new float[] { ch * 4 + i });
                }
            }
            var track = new AnimationTrack (sequence, AnimationTrack.Alpha);
            track.SetController (controller);

            // Keyframe = 0
            Assert.Equal (0.0f, track.Sample (0, 0));   // index=0, ch=0
            Assert.Equal (4.0f, track.Sample (0, 1));   // index=0, ch=1
            Assert.Equal (8.0f, track.Sample (0, 2));   // index=0, ch=2
            Assert.Equal (12.0f, track.Sample (0, 3));  // index=0, ch=3

            // Keyframe = 3
            Assert.Equal (3.0f, track.Sample (3, 0));   // index=3, ch=0
            Assert.Equal (7.0f, track.Sample (3, 1));   // index=3, ch=1
            Assert.Equal (11.0f, track.Sample (3, 2));  // index=3, ch=2
            Assert.Equal (15.0f, track.Sample (3, 3));  // index=3, ch=3
        }

        [Fact]
        public void TestReferences () {
            var controller = new AnimationController ();
            var keyseq     = new KeyframeSequence (4, 4, 1, KeyframeSequence.Step);
            var track      = new AnimationTrack (keyseq, AnimationTrack.Alpha);
            track.SetController (controller);

            var refs = track.References;

            Assert.Equal (2, refs.Length);
            Assert.Same (controller, refs[0]);
            Assert.Same (keyseq, refs[1]);
        }

        [Fact]
        public void TestDuplicate () {
            var controller = new AnimationController ();
            var keyseq     = new KeyframeSequence (4, 4, 1, KeyframeSequence.Step);
            var track      = new AnimationTrack (keyseq, AnimationTrack.Alpha);
            track.SetController (controller);
            track.UserID = 100;

            var dup = (AnimationTrack)track.Duplicate ();

            Assert.Equal (track.Controller, dup.Controller);
            Assert.Equal (track.UserID, dup.UserID);

        }
    }
}
